<template>
  <el-dialog
    v-model="visible"
    title="导出vue文件"
    class="export-dialog"
    width="80%"
  >
    <div id="editJsonCopy"></div>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="copyData"> 复制数据 </el-button>
        <el-button type="primary" @click="dialogExport"> 导出代码 </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
  import { ref, nextTick } from 'vue'
  import Clipboard from 'clipboard'
  import { ElMessage } from 'element-plus'
  import { aceEdit, objToStringify } from '@/utils/design'

  const visible = ref(false)
  const editor = ref()
  // 根据生成的json提取需要导入的组件，远程方法，检验方法
  const getObjHtml = (obj: any) => {
    let rulesMethods = ''
    const sourceFun = ''
    obj &&
      obj.list.forEach((item: any) => {
        if (item.customRules?.length) {
          // 使用自定义校验方法
          item.customRules.forEach((c: any) => {
            if (c.type === 'methods' && c.methods) {
              rulesMethods += `// todo 请完善${item.item.label}校验方法
  provide("${c.methods}", (rule, value, callback) => {
    if (value === '') {
      callback(new Error('Please input the password again'))
    } else if (value !== 'abc') {
      callback(new Error("Two inputs don't match!"))
    } else {
      callback()
    }
  })`
            }
          })
        }
        // if (item.config?.optionsType === 2 && item.config?.optionsFun) {
        //   // 单选多选下拉等方法设值
        //   // const optionsValue = ref([{label: "选项1", value: '1'}])
        //   // provide("getCheckbox", optionsValue)
        //   sourceFun += `// todo ${item.item.label}设置选项值\n`
        //   sourceFun += `const ${item.name}Option = ref([{label: "选项1", value: '1'}])\n`
        //   sourceFun += `provide("${item.config.optionsFun}", ${item.name}Option)\n`
        // }
      })
    return {
      rulesMethods: rulesMethods,
      sourceFun: sourceFun
    }
  }
  const open = (obj: any) => {
    visible.value = true
    const getHtml = getObjHtml(obj)
    const { submitUrl = '', editUrl = '', requestUrl = '' } = obj.config
    if (requestUrl) {
      // 从obj里删除使用props方式
      delete obj.config.requestUrl
    }
    if (editUrl) {
      // 从obj里删除使用props方式
      delete obj.config.editUrl
    }
    if (submitUrl) {
      // 从obj里删除使用props方式
      delete obj.config.submitUrl
    }

    const html = `<template>
  <div>
    <ak-form
      ref="formNameEl"
      :type="formType"
      :data="formData"
      request-url="${requestUrl}"
      submit-url="${submitUrl}"
      edit-url="${editUrl}"
      :before-submit="beforeSubmit">
    </ak-form>
  </div>
</template>
<script setup lang="ts">
  import { ref, computed, provide } from 'vue'
  const formNameEl = ref()
  const formData = ref(${objToStringify(obj)})
    // todo 存在编辑时，可根据路由等参数设置当前表单模式 1新增 2编辑
  const formType = computed(() => {
     return 1
  })
  ${getHtml.rulesMethods}
  ${getHtml.sourceFun}
  // 表单提交时参数处理
  const beforeSubmit = (params)=>{
    // 如编辑时添加参数
    //  params.id='xxx'
    return params
  }

<\/script>`
    nextTick(() => {
      editor.value = aceEdit(html, 'editJsonCopy', 'html')
    })
  }
  // 打开弹窗，导出表格数据
  const openTable = (obj: any) => {
    const openDialog = obj.config?.openType === 'dialog'
    const dialogWidth = obj.config?.dialogWidth || '600px'
    const requestUrl = obj.config?.requestUrl || ''
    if (requestUrl) {
      // 从obj里删除使用props方式
      delete obj.config.requestUrl
    }
    const deleteUrl = obj.config?.deleteUrl || ''
    if (deleteUrl) {
      // 从obj里删除使用props方式
      delete obj.config.deleteUrl
    }
    let formHtml = ''
    let formContent = ''
    let listBtn = ''
    if (openDialog) {
      // 弹窗打开
      listBtn = `@btn-click="listBtnClick"`
      formHtml = `<el-dialog
      destroy-on-close
      v-model="dialog.visible"
      :title="dialog.title"
      width="${dialogWidth}"
    >
      <ak-form
        ref="formEl"
        :formData="formData"
        :dict="dialog.dict"
        :type="dialog.formType"
        requestUrl=""
        submit-url=""
        edit-url=""
        :before-submit="beforeSubmit"
        :after-submit="afterSubmit"
        @btn-click="dialogBtnClick"
      ></ak-form>
    </el-dialog>`
      formContent = `const formEl = ref()
  // todo 表单数据可从设计表单导出vue文件或保存生成脚本
  const formData = ref({list:[],form:{},config:{}})
  const dialog = reactive({
    visible: false,
    title: '',
    formType: 1,
    dict: {},
    editId: ''
  })
  const listBtnClick = (btn, row) => {
    // 使用弹窗方式打开新增编辑
    if (btn.key === 'add' || btn.key === 'edit') {
      // 打开弹窗
      dialog.visible = true
      dialog.title = btn.key === 'add' ? '新增' : '编辑'
      dialog.formType = btn.key === 'add' ? 1 : 2
      dialog.editId = row && row.id

      if (btn.key === 'add' && formData.value.config?.addLoad) {
        // 添加时需要加载数据
        nextTick(() => {
          formEl.value.getData()
        })
      }
      // 编辑，根据id加载
      if (btn.key === 'edit') {
        nextTick(() => {
       // eslint-disable-next-line no-irregular-whitespace
       　 // todo 当表单内容字段比较少，所需值从列表数据就可以获取
       // eslint-disable-next-line no-irregular-whitespace
       // eslint-disable-next-line no-irregular-whitespace
       　　// formEl.value.setValue(row)
          formEl.value.getData({ id: row.id })
        })
      }
    }
  }
  // 提交表单前事件
  const beforeSubmit = (params) => {
    if(dialog.formType===2){ // 编辑模式下添加参数
      params.id = dialog.editId
    }
    return params
  }
  // 提交表单后事件
  const afterSubmit = (type) => {
    if (type === 'success') {
      // 添加成功，刷新列表数据
      closeResetDialog()
      tableListEl.value.getListData()
    }
  }
  // 关闭弹窗并重置表单，否则下次打开会保留上次数据
  const closeResetDialog = () => {
    dialog.visible = false
    dialog.editId = ''
    // formEl.value.resetFields() // 重置表单
  }
  //　点击弹窗取消按钮时
  const dialogBtnClick = (type) => {
    if (type === 'reset') {
      closeResetDialog()
    }
  }
`
    }
    visible.value = true
    const html = `<template>
  <div>
    <ak-list
      ref="tableListEl"
      request-url="${requestUrl}"
      delete-url="${deleteUrl}"
      :search-data="searchData"
      :data="tableData"
      ${listBtn}>
    </ak-list>
    ${formHtml}
  </div>
</template>

<script setup>
  // import {useRoute, useRouter} from 'vue-router'
  import { ref, nextTick,reactive } from 'vue'
  // const route = useRoute()
  // const router = useRouter()
  const tableListEl = ref()
  const searchData = ref({})
  const tableData = ref(${objToStringify(obj)})
  ${formContent}
<\/script>`
    nextTick(() => {
      editor.value = aceEdit(html, 'editJsonCopy', 'html')
    })
  }
  const openScreen = (obj: any) => {
    visible.value = true
    let styleCss = ''
    let globalData = ''
    let globalImport = ''
    const style = obj.config.style
    if (style) {
      styleCss = `<style>${style}
<\/style>`
    }
    if (obj.config.requestUrl) {
      // 全局大屏数据
      globalImport = `import { getRequest } from '@/api'`
      globalData = `
      const {requestUrl,method} = screenData.value.config
  getRequest(requestUrl,{},{method:method})
  .then((res: any) => {
      // 这里处理数据，直接对screenData设置值即可，无须使用全局或afterFetch之类的方法设值
      //
   })`
    }
    const html = `<template>
  <div :style="screenStyle" class="design-canvas">
    <ak-screen
      v-for="(element, index) in screenData.list"
      :key="index"
      :data="element"
    ></ak-screen>
  </div>
</template>

<script setup lang="ts">
  import { ref, computed, provide } from 'vue'
  ${globalImport}
  import AKScreen from '@/views/design/screen/components/screen.vue' //可根据需求是否全局注册
  const loading = ref(true)
  const screenData = ref(${objToStringify(obj)})
  const screenStyle = computed(() => {
    const { width, height, background, primary } = screenData.value.config
    return {
      width: width,
      height: height,
      background: background,
      color: primary,
      position: 'relative'
    }
  })
  ${globalData}
<\/script>
${styleCss}`
    nextTick(() => {
      editor.value = aceEdit(html, 'editJsonCopy', 'html')
    })
  }

  const copyData = (e: any) => {
    nextTick(() => {
      const clipboard: any = new Clipboard(e.target, {
        text: () => {
          return editor.value.getValue()
        }
      })
      clipboard.on('success', function () {
        ElMessage({
          message: '复制成功！',
          type: 'success'
        })
        clipboard.destroy()
      })
      clipboard.on('error', function () {
        ElMessage.error('复制失败')
        clipboard.destroy()
      })
      clipboard.onClick(e)
    })
  }
  // 导出文件
  const dialogExport = () => {
    const content = 'data:text/csv;charset=utf-8,' + editor.value?.getValue()
    const fileName = new Date().getTime() + '.vue'
    const encodedUri = encodeURI(content)
    const actions = document.createElement('a')
    actions.setAttribute('href', encodedUri)
    actions.setAttribute('download', fileName)
    actions.click()
  }
  defineExpose({
    open,
    openTable,
    openScreen
  })
</script>
